﻿using Microsoft.Extensions.FileProviders;
using Newtonsoft.Json;
using Nop.Core.Caching;
using Nop.Core.Domain.Shipping;
using Nop.Services.Common;
using Nop.Services.Logging;
using Nop.Services.Shipping.Tracking;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;

namespace Nop.Plugin.Shipping.FixedByWeightByTotal
{
    public class ChinaShipmentTracker : IShipmentTracker
    {

        #region json model
        public class ListItem
        {
            /// <summary>
            /// 
            /// </summary>
            public DateTime time { get; set; }
            /// <summary>
            /// 快件已代收点签收[签收]
            /// </summary>
            public string status { get; set; }
        }

        public class Result
        {
            /// <summary>
            /// 
            /// </summary>
            public string number { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string type { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public List<ListItem> list { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string deliverystatus { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string issign { get; set; }
            /// <summary>
            /// 优速物流
            /// </summary>
            public string expName { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string expSite { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string expPhone { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string logo { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string courier { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string courierPhone { get; set; }
        }

        public class Root
        {
            /// <summary>
            ///          201	快递单号错误 status：快递单号错误
            ///203	快递公司不存在 status：快递公司不存在
            ///204	快递公司识别失败 status：快递公司识别失败
            ///205	没有信息 status：没有信息
            ///207	该单号被限制，错误单号 status：该单号被限制，错误单号；一个单号对应多个快递公司，请求须指定快递公司
            ///0	正常 status：正常查询
            /// </summary>
            public string status { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string msg { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public Result result { get; set; }
        }

        #endregion

        private readonly ILogger _logger;
        private readonly IGenericAttributeService _genericAttributeService;
        private IStaticCacheManager _cacheManager;
        public ChinaShipmentTracker(ILogger logger, IGenericAttributeService genericAttributeService, IStaticCacheManager cacheManager)
        {
            this._logger = logger;
            this._genericAttributeService = genericAttributeService;
            this._cacheManager = cacheManager;
        }


        private IList<ShipmentStatusEvent> Stream2List(Stream stream, Shipment shipment)
        {
            using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                string responseJson = reader.ReadToEnd();
                var root = JsonConvert.DeserializeObject<Root>(responseJson);
                if (root.status.Equals("0"))
                {

                    if (root.result.list.Count > 0)
                    {
                        var result = new List<ShipmentStatusEvent>();
                        foreach (var item in root.result.list)
                        {
                            result.Add(new ShipmentStatusEvent()
                            {
                                Date = item.time,
                                EventName = item.status
                            });
                        }

                        result.Add(new ShipmentStatusEvent()
                        {
                            Date = root.result.list.Last().time,
                            EventName = $"快件由{root.result.expName}({root.result.expSite})承运,联系电话:{root.result.expPhone}"
                        });
                        if (root.result.issign == "1")
                        {
                            WriteFileCache(responseJson, shipment, root.result.type);
                        }
                        return result;
                    }
                }
                else
                {
                    _logger.Information($"物流单号查询结果返回不匹配:{responseJson}");

                }
            }
            return null;
        }

        void WriteFileCache(string responseJson, Shipment shipment, string type)
        {
            try
            {
                _genericAttributeService.SaveAttribute(shipment, "CHINA_Shipment_TYPE", type);
                var jsonFile = Path.Combine(GetAssemblyPath(), nameof(ChinaShipmentTracker), $"{shipment.Id}_{shipment.TrackingNumber}.json");
                if (!Directory.Exists(Path.GetDirectoryName(jsonFile)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(jsonFile));
                }
                File.WriteAllText(jsonFile, responseJson, Encoding.UTF8);
            }
            catch (Exception ex)
            {
                _logger.Information("物流缓存写入错误", ex);
            }

        }

        IList<ShipmentStatusEvent> FromApi(Shipment shipment)
        {
            var url = $"http://wuliu.market.alicloudapi.com/kdi?no={shipment.TrackingNumber}";
            var type = _genericAttributeService.GetAttribute<string>(shipment, "CHINA_Shipment_TYPE");
            if (!string.IsNullOrEmpty(type))
            {
                url += $"&type={type}";
            }
            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Method = WebRequestMethods.Http.Get;
            request.Headers.Add("Authorization", "APPCODE 421620d6ab574d3f945e0d1c14002149");
            try
            {
                using (var response = request.GetResponse())
                {
                    return Stream2List(response.GetResponseStream(), shipment);

                }
            }
            catch (Exception ex)
            {
                _logger.Error("物流信息获取错误", ex);
            }
            return null;
        }

        IList<ShipmentStatusEvent> FromFile(Shipment shipment)
        {
            var jsonFile = Path.Combine(GetAssemblyPath(), nameof(ChinaShipmentTracker), $"{shipment.Id}_{shipment.TrackingNumber}.json");
            if (File.Exists(jsonFile))
            {
                using (var stream = File.OpenRead(jsonFile))
                {
                    return Stream2List(stream, shipment);

                }
            }
            return null;
        }

        private IList<ShipmentStatusEvent> Query(Shipment shipment)
        {
            var list = FromFile(shipment);
            if (list == null)
            {
                list = FromApi(shipment);
            }
            return list;
        }


        string GetAssemblyPath()
        {
            string codeBase = Assembly.GetEntryAssembly().CodeBase;
            UriBuilder uri = new UriBuilder(codeBase);
            string path = Uri.UnescapeDataString(uri.Path);
            return Path.GetDirectoryName(path);
        }

        public IList<ShipmentStatusEvent> GetShipmentEvents(Shipment shipment)
        {
            if (shipment == null || string.IsNullOrEmpty(shipment.TrackingNumber))
            {
                return new List<ShipmentStatusEvent>();
            }
            var list = this._cacheManager.Get<IList<ShipmentStatusEvent>>($"{nameof(ChinaShipmentTracker)}_Shipment_{shipment.Id}_{shipment.TrackingNumber}", () => { return Query(shipment); }, 1);
            if (list == null)
                return new List<ShipmentStatusEvent>();
            else
                return list;
        }

        public string GetUrl(Shipment shipment)
        {
            return "https://m.kuaidi100.com/result.jsp?nu=" + shipment.TrackingNumber;
        }



        public bool IsMatch(Shipment shipment)
        {
            return true;
        }
    }
}
